package cn.seem.realm;

import cn.seem.model.User;
import cn.seem.service.UserService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthenticatingRealm;

import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * Realm是接口，一般不会直接使用它，直接使用的是它的实现类
 *      org.apache.shiro.realm.AuthenticatingRealm   如果只做认证使用这个就好  只重写：doGetAuthenticationInfo
 *      org.apache.shiro.realm.AuthorizingRealm      如果还想做授权使用这个就好
 *          AuthorizingRealm 扩展了  AuthenticatingRealm 但是没有实现父类的doGetAuthenticationInfo(AuthenticationToken)
 *          同时还提供了自己特有的方法：doGetAuthorizationInfo(PrincipalCollection)
 */
public class UserRealm extends AuthorizingRealm {

    private UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    /**
     * 认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //-- 在控制器中我们封装了UsernamePasswordToken， 该token是参数AuthenticationToken的孙子！！
        System.out.println("realm" + authenticationToken.hashCode());

        String userName = (String) authenticationToken.getPrincipal();//-- 获取当前用户（）

        //-- 连接mybatis,查询密码，角色，权限
        User user = userService.findUserByName(userName);
        System.out.println("查询的UserName是"+user.getUserName());
        /*
            Object principal        当前用户
            Object credentials,     数据库中查询出来的密码
            String realmName        realm的名称
         */
        //-- 细节问题： 密码是明文的！
        ByteSource salt = ByteSource.Util.bytes(userName);
        //-- 如果不带盐值加密，就是构造方法少了一个参数：salt
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userName, "72e2953d400063c9c65d04d338e965da", salt,this.getName());
        return info;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }
}
